#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <vector>
#include <ctime>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"

#define PROCESS_NUM 10  //创建进程数
std::vector<task> tasks;


//先描述管道
class channel
{
public:
    channel(int fd, pid_t id, const std::string& name)
        :_fd(fd),
        _id(id),
        _name(name)
    {}
public:
    int _fd;            
    pid_t _id;
    std::string _name;
};


void slaver()
{
    while(true)
    {
        sleep(2);
        int command = 0;    //任务码
        ssize_t n = read(0, &command, sizeof(int));
        if(n > 0)
        {
            std::cout << "father assign task to slaver:" << getpid() << std::endl;
            tasks[command]();//执行任务
        }
        if(n == 0)
        {
            break;
        }
    }

}

void Load_task(std::vector<task>* tasks)
{
    tasks->push_back(task1);
    tasks->push_back(task2);
    tasks->push_back(task3);
    tasks->push_back(task4);
}

int main()
{

    //添加任务
    Load_task(&tasks);
    
    //再组织起来
    std::vector<channel> channels;

    //创建10个进程,建立管道
    for(int i = 0;i<PROCESS_NUM;i++)
    {
        int pipefd[2] = {0};
        int ret = pipe(pipefd);//建立管道
        if(ret < 0)
        {
            perror("pipe");
        }

        //创建子进程
        pid_t id = fork();
        if(id < 0) 
        {
            perror("fork");
        }
        if(id == 0)
        {
            //child
            close(pipefd[1]);
            dup2(pipefd[0], 0);
            slaver();//子进程解决问题

            exit(0);
        }

        //father
        close(pipefd[0]);
        std::string name = "process-" + std::to_string(id);
        channels.push_back(channel(pipefd[1], id, name));

    }


    //std::cout << tasks.size() << std::endl;
    int which = 0;
    srand(time(nullptr));
    //分派任务
    int cnt = 5;
    while(cnt--)
    //while(true)
    {

        //选择任务
        int command = rand() % tasks.size();

        //发送任务
        write(channels[which]._fd, &command, sizeof(command));

        //给子进程轮询分派任务
        ++which;
        which %= channels.size();
    }


    //清理
    for(int i = 0;i<PROCESS_NUM;i++)
    {
        close(channels[i]._fd);//关闭写端
    }
    for(int i = 0;i<PROCESS_NUM;i++)
    {
        waitpid(channels[i]._id, nullptr, 0);
    }
    
    std::cout << "finish" << std::endl;

    return 0;
}